import axios from "axios";
import QS from "@/axios/qs";

//常量
export const EVENT_LOADINITDATA = 'loadInitData' //全局定时刷新数据事件

// 参数编码
const ethers = require('ethers')
const AbiCoder = ethers.utils.AbiCoder;
const ADDRESS_PREFIX_REGEX = /^(41)/;
const ADDRESS_PREFIX = "41";

//本地储存处理
export function getLocalStorage (key,defaultValue) {
	let value = localStorage.getItem(key);
	if (value === null || typeof value === "undefined") {
		value = defaultValue ? defaultValue : "";
	}
	return value;
}

export function setLocalStorage (key,value) {
	localStorage.setItem(key,value);
}

/**
 * @description  截取返回数据中的有效数据
 * @param {Object} value 合约返回数据
 * @param {Object} index  第几个片段
 * @param {Object} length 片段长度
 */
export function getEffectiveValue (value, index, length) {
    if (value) {
        let size = value.length;
        let start = (index - 1) * length;
        let end = index * length;
        if (size >= end) {
            return value.substring(start, end);
        } else if (size < end && size >= start) {
            return value.substring(start);
        } else {
            return value;
        }
    }
}

/**
 * p率精度除，返回正常数字，由于提交时是要*1000，所以得到数据后也要除1000
 * @param value
 * @param precision
 * @returns {number}
 */
export function oddsPrecisionToNum(value,precision=3){
    return isNaN(value) ? '加载中' : value / Math.pow(10,precision)
}
/**
 * 除按精度除，返回正常数字
 * @param value
 * @param precision 默认是8
 */
export function precisionToNum(value, precision =8){
    return value / Math.pow(10,precision)
}

/**
 * 按精度格式化数据
 * @param {Object} value
 * @param {Object} precision
 */
export function formatNum (value, precision) {
    let v = parseFloat(value);
    if (!isNaN(v)) {
        value = v.toFixed(precision);
        toNonExponential(value);
    }
    return value;
}


/**
 * @description  将数字转换为尾部0剔除的非科学计数法的数字
 * @param {Object} num
 */
export function toNonExponential (num) {
    try {
        num = new Number(num);
        var m = num.toExponential().match(/\d(?:\.(\d*))?e([+-]\d+)/);
        return num.toFixed(Math.max(0, (m[1] || '').length - m[2]));
    } catch (e) {
        return num;
    }
}


/**
 * @description  将时间戳格式化为标准时间  yyyy-MM-dd hh:mm:ss
 * @param {Object} timestamp 时间戳
 */
export function timestaptodate (timestamp) {
    return timestampToDate(timestamp, 'yyyy-MM-dd hh:mm:ss');
}

/**
 * @description  将时间戳格式化化为对应的时间格式
 * @param {Object} timestamp 时间戳
 * @param {Object} fmt 格式化模版
 */
export function timestampToDate (timestamp, fmt) {
    return new Date(timestamp).format(fmt);
}



/**
 * @description  根据时间周期长度分段显示
 * @param {Object} during 时间周期
 */
export function getFormatDuringTime (during) {
    let s = Math.floor(during / 1) % 60;
    during = Math.floor(during / 60);
    let i = during % 60;
    during = Math.floor(during / 60);
    let h = during % 24;
    during = Math.floor(during / 24);
    let d = during;
    let rsp = "";
    if (d > 0) {
        rsp = (d + '天' + h + '小時' + i + '分');
    } else if (h > 0) {
        rsp = h + '小時' + i + '分' + s + '秒';
    } else {
        rsp = i + '分' + s + '秒';
    }
    return rsp;
}


/**
 * @description  时间周期分段显示 en
 * @param {Object} value 时间周期
 */
export function formatSeconds (value) {
    let secondTime = parseInt(value); // 秒
    let minuteTime = 0; // 分
    let hourTime = 0; // 小時
    if (secondTime > 60) { //如果秒數大於60，將秒數轉換成整數
        //獲取分鐘，除以60取整數，得到整數分鐘
        minuteTime = parseInt(secondTime / 60);
        //獲取秒數，秒數取佘，得到整數秒數
        secondTime = parseInt(secondTime % 60);
        //如果分鐘大於60，將分鐘轉換成小時
        if (minuteTime > 60) {
            //獲取小時，獲取分鐘除以60，得到整數小時
            hourTime = parseInt(minuteTime / 60);
            //獲取小時後取佘的分，獲取分鐘除以60取佘的分
            minuteTime = parseInt(minuteTime % 60);
        }
    }
    let result = "" + parseInt(secondTime) + "";

    if (minuteTime > 0) {
        result = "" + parseInt(minuteTime) + ":" + result;
    }
    if (hourTime > 0) {
        result = "" + parseInt(hourTime) + ":" + result;
    }
    return result;
}

/**
 * todo 注意这里用了msgInterface，而里面用了this.LangSet，没法用了
 * 智能合约广播回调
 * @param ACTION 操作标题
 * @param MESSAGE 操作详情
 * @param extraCallback 额外的业务处理
 * @returns {function(*=, *=): void}
 */
// export const smartContractBroadcastCallback = function (ACTION, MESSAGE, extraCallback) {
//     return (status, txid) => {
//         if (status === 0) { //失敗
//             msgInterface(ACTION, '', -1, '', MESSAGE);
//         } else if (status === 1) { //成功
//             msgInterface(ACTION, '', 2, 'https://tronscan.io/#/transaction/' + txid, MESSAGE);
//         } else if (status === -1) { //取消
//             msgInterface(ACTION, '', 3, '', MESSAGE);
//         }
//         extraCallback(status, txid)
//     }
// }

/**
 * todo  见上面和下面
 * 触发智能合约的最终交易确认回调
 * @param ACTION 动作
 * @param MESSAGE 动作详情
 * @returns {function(*, *): void}
 */
// export const smartContractConfirmCallback = function (ACTION, MESSAGE) {
//     return (txid, status) => {//区块链结果查询回调的信息，应该是不影响用户操作的，因为是几秒钟后才显示的
//         if (status === "SUCCESS") {
//             this.$notify({
//                     title   : this.LangSet(['成功', 'SUCCESS']),
//                     message : ACTION + MESSAGE,
//                     type    : 'success',
//                     duration: 10000,
//                 },
//             );
//         } else if (status === "OUT_OF_ENERGY") {
//             this.$notify.error({
//                 title   : ACTION + MESSAGE + this.LangSet(['失敗', 'FAIL']),
//                 message : this.LangSet(['錢包中請至少保留', 'Minimum wallet balance']) + '20TRX',
//                 duration: 10000,
//             });
//         } else {
//             this.$notify.error({
//                 title   : this.LangSet(['失敗', 'FAIL']),
//                 message : ACTION + MESSAGE,
//                 duration: 10000,
//             });
//         }
//     }
// }


/**
 * todo 注意，这里面用了LangSet
 * 鎖定和鎖定的統一提示層入口，最早用于矿池，现在用于所有操作
 * @param prefix 主标题
 * @param amount 操作数量，最早用到矿池锁仓和解锁
 * @param code 信息类型，显示不同的内容
 * @param url 交易查询地址
 * @param token
 */
// export function msgInterface (prefix, amount = 0 , code = 1, url = '', token='') {
//     let that = this;
//     let title = prefix
//     let html = '';
//     let type = ''//用于alert的类型
//     amount ? title = title + amount : title = title
//     title += token //有的是授权币的操作，所以这里要显示token
//
//     if (code == 1) {
//         type = 'info'
//         html += '<i class="c-333 f70 fa fa-spinner fa-pulse"></i>';
//         html += '<div class="f22 mt10">' + that.LangSet(['等待您的確認', 'Waiting for your confirmation']) + '</div>';
//         html += '<div class="f14 mt10">' + that.LangSet(['請在您的錢包中確認', 'Please confirm in your wallet']) + '</div>';
//     } else if (code == 2) {
//         type = 'success'
//         html += '<i class="c-green f100 fa fa-check-circle"></i>';
//         html += '<div class="f22 mt10">' + that.LangSet(['交易已提交', 'Deal submited']) + '</div>';
//         html += '<div class="f14 mt10"><a href="' + url + '" target="_self" class="c-red">' + that.LangSet([
//             '在 TRONSCAN 上查看', 'View on TRONSCAN'
//         ]) + ' >></a></div>';
//
//     } else if (code == 3) {
//         type = 'warning'
//         html += '<i class="c-red mt20 f100 fa fa-exclamation-circle"></i>';
//         html += '<div class="f24 mt20">' + that.LangSet(['交易已取消', 'Deal cancelled']) + '</div>';
//     } else if (code == -1) {
//         type = 'error'
//         html += '<i class="c-red mt20 f100 fa fa-exclamation-circle"></i>';
//         html += '<div class="f24 mt20">' + that.LangSet(['交易失敗', 'Deal failed']) + '</div>';
//     } else if (code == 0) {
//         type = 'error'
//         html += '<i class="c-red mt20 f100 fa fa-exclamation-circle"></i>';
//         html += '<div class="f24 mt20">' + that.LangSet(['錢包中請保留20TRX，確保交易順暢',
//             'Please keep 20trx in your wallet to ensure smooth transaction'
//         ]) + '</div>';
//     }
//     msgboxLayer(title, html)
// }

/**
 * @description  弹出层,layer
 * @param {Object} title 标题
 * @param {Object} html  内容
 */
export function msgboxLayer (title, html,type='') {
    // html = "<div class='p20 center'>" + html + "</div>";
    // layer.closeAll(); //關閉之前的
    // layer.open({
    //     type: 1,
    //     shadeClose: true,
    //     area: ['350px', '300px'],
    //     title: title,
    //     content: html
    // });
    Swal.close()
    Swal.fire({
        title:title,
        html: html,
        type: type,
        confirmButtonText: '確定'
    })
}


/**
 * @description  通过页面地址获取参数值
 * @param {Object} variable
 */
export function getUrlParam (variable) {
    var query = window.location.hash.replace(/\#.*\?/gi,''); //修改成适用hash路由的参数
    var vars = query.split("&");
    for (var i = 0; i < vars.length; i++) {
        var pair = vars[i].split("=");
        if (pair[0] == variable) {
            return pair[1];
        }
    }
    return (false);
}


/**
 * @description 获取trx价格
 * @param {Object} callback
 */
export function getTrxPrice (callback) {
    $.ajax({
        url: 'https://c.tronlink.org/v1/cryptocurrency/getprice?symbol=TRX&convert=USD',
        type: 'GET',
        dataType: 'JSON'
    }).done((res) => {
        if (res && res.status && res.status.error_code === 0) {
            callback(res.data.TRX.quote.USD.price);
        }
    }).fail((res) => {
        callback("NAN");
    });
}


/**
 * @desc: 参数转换URL????? ??这个是从别的地方提取出来的，但原来的未改
 * @date: 2021-07-13
 */
export const parameterConversionURL = function(str) {
    // 参数转换url形式
    let parse = JSON.parse(JSON.stringify(str));
    let params = Object.keys(str).map(function (key) {
        return encodeURIComponent(key) + "=" + encodeURIComponent(parse[key])
    }).join("&");
    return params;
}


//编码参数
export function encodeParams(inputs) {
    let typesValues = inputs
    let parameters = ''

    if (typesValues.length == 0)
        return parameters
    const abiCoder = new AbiCoder();
    let types = [];
    const values = [];

    for (let i = 0; i < typesValues.length; i++) {
        let {type, value} = typesValues[i];
        if (type == 'address')
            value = value.replace(ADDRESS_PREFIX_REGEX, '0x');
        else if (type == 'address[]')
            value = value.map(v => toHex(v).replace(ADDRESS_PREFIX_REGEX, '0x'));
        types.push(type);
        values.push(value);
    }

    try {
        parameters = abiCoder.encode(types, values).replace(/^(0x)/, '');
    } catch (ex) {
        console.log(ex);
    }
    return parameters
}


//判断是否为空
export const strItIsEmpty = function (rs) {
    if (rs == null || rs == undefined || rs == false || rs == '') {
        return true;
    }
    return false;
}

//替换0等特殊无用字符串
export function delOutTheNoise(hex){
    hex = hex.replace(/^0x/i, '');

    //兑换多余的符号0
    hex = hex.replace(/^(?:00)*/, '');
    hex = hex.split("").reverse().join("");
    hex = hex.replace(/^(?:00)*/, '');
    hex = hex.split("").reverse().join("");
    return hex;
}

/**
 * 16进制转换字符串
 */
export function hexToUtf8(hex) {
    delOutTheNoise(hex);

    //替换乱码字符串
    return tronWeb.toUtf8(hex).replace(/[^-|^（|^）|^\d|^\[a-zA-Z\]|^\[\u4e00-\u9fa5\]]/g, '');
}

//按段截取。例如截取：0-128，就变成了（0*68，0*68+128）从第0位开赛，截取128位
export function stringInterceptLimit(content, start, end) {
    let index1 = 68 * start;
    let index2 = (68 * start) + end;

    let hex = (content.substring(index1, index2));
    hex = "0x" + hex;
    return hex;
}

/**
 * 把对象中的属性值按类型清空,返回新的对象
 * @param _tempo 要处理的对象
 */
export function objectAttrClear(o){
    let _tempo = {...o}
    Object.keys(_tempo).forEach((key)=> {
        if(typeof _tempo[key] == 'number'){ //数字
            _tempo[key] = 0
        }else if(typeof _tempo[key] == 'string'){//字符串
            _tempo[key] = ''
        }else if(_tempo[key] instanceof Array == true){ //数组
            _tempo[key] = []
        }
    })
    return _tempo
}
